package com.datagateway.component;

import com.datagateway.model.ProcessedData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 数据血缘追踪器
 * 负责追踪数据来源和处理链路，提供数据治理能力
 * 
 * @author Data Gateway Team
 * @version 1.0.0
 */
@Component
public class DataLineageTracker {

    private static final Logger logger = LoggerFactory.getLogger(DataLineageTracker.class);

    @Autowired
    private AlertManager alertManager;

    @Autowired
    private SystemMonitor systemMonitor;

    /**
     * 数据血缘关系存储
     */
    private final ConcurrentHashMap<String, DataLineage> lineageMap = new ConcurrentHashMap<>();

    /**
     * 数据血缘统计信息
     */
    private final AtomicLong totalLineageRecords = new AtomicLong(0);
    private final AtomicLong totalLineageQueries = new AtomicLong(0);
    private final AtomicLong totalLineageUpdates = new AtomicLong(0);

    /**
     * 血缘追踪配置
     */
    private boolean lineageTrackingEnabled = true;
    private int maxLineageDepth = 10;
    private long lineageRetentionDays = 30;

    /**
     * 记录数据血缘关系
     * 
     * @param data 处理后的数据
     * @param sourceInfo 源信息
     * @param transformationInfo 转换信息
     * @param targetInfo 目标信息
     */
    public void recordDataLineage(ProcessedData data, SourceInfo sourceInfo, 
                                TransformationInfo transformationInfo, TargetInfo targetInfo) {
        if (!lineageTrackingEnabled) {
            return;
        }

        try {
            String dataId = data.getId();
            
            // 创建数据血缘记录
            DataLineage lineage = new DataLineage(
                dataId,
                sourceInfo,
                transformationInfo,
                targetInfo,
                System.currentTimeMillis()
            );
            
            // 存储血缘关系
            lineageMap.put(dataId, lineage);
            totalLineageRecords.incrementAndGet();
            
            logger.debug("记录数据血缘: {} -> {} -> {}", 
                        sourceInfo.getSourceId(), transformationInfo.getTransformationId(), targetInfo.getTargetId());
            
            // 记录血缘统计
            systemMonitor.recordRouteEvent("lineage", dataId, targetInfo.getTargetId());
            
        } catch (Exception e) {
            logger.error("记录数据血缘失败: {}", data.getId(), e);
            alertManager.sendSystemErrorAlert("数据血缘记录失败", e.getMessage());
        }
    }

    /**
     * 记录数据血缘关系（简化版本）
     * 
     * @param data 处理后的数据
     */
    public void recordDataLineage(ProcessedData data) {
        if (!lineageTrackingEnabled) {
            return;
        }

        try {
            // 从数据中提取血缘信息
            SourceInfo sourceInfo = extractSourceInfo(data);
            TransformationInfo transformationInfo = extractTransformationInfo(data);
            TargetInfo targetInfo = extractTargetInfo(data);
            
            recordDataLineage(data, sourceInfo, transformationInfo, targetInfo);
            
        } catch (Exception e) {
            logger.error("记录数据血缘失败: {}", data.getId(), e);
        }
    }

    /**
     * 查询数据血缘关系
     * 
     * @param dataId 数据ID
     * @return 数据血缘关系
     */
    public DataLineage queryDataLineage(String dataId) {
        try {
            totalLineageQueries.incrementAndGet();
            
            DataLineage lineage = lineageMap.get(dataId);
            if (lineage != null) {
                logger.debug("查询数据血缘: {} -> {}", dataId, lineage.getTargetInfo().getTargetId());
            }
            
            return lineage;
            
        } catch (Exception e) {
            logger.error("查询数据血缘失败: {}", dataId, e);
            return null;
        }
    }

    /**
     * 查询数据血缘链路
     * 
     * @param dataId 数据ID
     * @param maxDepth 最大深度
     * @return 数据血缘链路
     */
    public List<DataLineage> queryDataLineageChain(String dataId, int maxDepth) {
        try {
            totalLineageQueries.incrementAndGet();
            
            List<DataLineage> lineageChain = new ArrayList<>();
            Set<String> visited = new HashSet<>();
            
            String currentDataId = dataId;
            int depth = 0;
            
            while (currentDataId != null && depth < maxDepth && !visited.contains(currentDataId)) {
                DataLineage lineage = lineageMap.get(currentDataId);
                if (lineage == null) {
                    break;
                }
                
                lineageChain.add(lineage);
                visited.add(currentDataId);
                
                // 查找上游数据
                currentDataId = findUpstreamDataId(lineage);
                depth++;
            }
            
            logger.debug("查询数据血缘链路: {} -> {} 条记录", dataId, lineageChain.size());
            
            return lineageChain;
            
        } catch (Exception e) {
            logger.error("查询数据血缘链路失败: {}", dataId, e);
            return new ArrayList<>();
        }
    }

    /**
     * 查询数据影响分析
     * 
     * @param dataId 数据ID
     * @param maxDepth 最大深度
     * @return 影响的数据列表
     */
    public List<DataLineage> queryDataImpactAnalysis(String dataId, int maxDepth) {
        try {
            totalLineageQueries.incrementAndGet();
            
            List<DataLineage> impactList = new ArrayList<>();
            Set<String> visited = new HashSet<>();
            Queue<String> queue = new LinkedList<>();
            
            queue.offer(dataId);
            visited.add(dataId);
            int depth = 0;
            
            while (!queue.isEmpty() && depth < maxDepth) {
                int size = queue.size();
                depth++;
                
                for (int i = 0; i < size; i++) {
                    String currentDataId = queue.poll();
                    DataLineage lineage = lineageMap.get(currentDataId);
                    
                    if (lineage != null) {
                        impactList.add(lineage);
                        
                        // 查找下游数据
                        List<String> downstreamIds = findDownstreamDataIds(lineage);
                        for (String downstreamId : downstreamIds) {
                            if (!visited.contains(downstreamId)) {
                                queue.offer(downstreamId);
                                visited.add(downstreamId);
                            }
                        }
                    }
                }
            }
            
            logger.debug("查询数据影响分析: {} -> {} 条记录", dataId, impactList.size());
            
            return impactList;
            
        } catch (Exception e) {
            logger.error("查询数据影响分析失败: {}", dataId, e);
            return new ArrayList<>();
        }
    }

    /**
     * 更新数据血缘关系
     * 
     * @param dataId 数据ID
     * @param lineage 新的血缘关系
     */
    public void updateDataLineage(String dataId, DataLineage lineage) {
        try {
            lineageMap.put(dataId, lineage);
            totalLineageUpdates.incrementAndGet();
            
            logger.debug("更新数据血缘: {}", dataId);
            
        } catch (Exception e) {
            logger.error("更新数据血缘失败: {}", dataId, e);
        }
    }

    /**
     * 删除数据血缘关系
     * 
     * @param dataId 数据ID
     */
    public void deleteDataLineage(String dataId) {
        try {
            DataLineage removed = lineageMap.remove(dataId);
            if (removed != null) {
                logger.debug("删除数据血缘: {}", dataId);
            }
            
        } catch (Exception e) {
            logger.error("删除数据血缘失败: {}", dataId, e);
        }
    }

    /**
     * 清理过期的血缘记录
     */
    public void cleanupExpiredLineage() {
        try {
            long cutoffTime = System.currentTimeMillis() - (lineageRetentionDays * 24 * 60 * 60 * 1000);
            int removedCount = 0;
            
            Iterator<Map.Entry<String, DataLineage>> iterator = lineageMap.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, DataLineage> entry = iterator.next();
                DataLineage lineage = entry.getValue();
                
                if (lineage.getTimestamp() < cutoffTime) {
                    iterator.remove();
                    removedCount++;
                }
            }
            
            logger.info("清理过期血缘记录: {} 条", removedCount);
            
        } catch (Exception e) {
            logger.error("清理过期血缘记录失败", e);
        }
    }

    /**
     * 从数据中提取源信息
     * 
     * @param data 处理后的数据
     * @return 源信息
     */
    private SourceInfo extractSourceInfo(ProcessedData data) {
        return new SourceInfo(
            "kafka:" + data.getSourceTopic(),
            data.getSourceTopic(),
            data.getPartition(),
            data.getOffset(),
            System.currentTimeMillis()
        );
    }

    /**
     * 从数据中提取转换信息
     * 
     * @param data 处理后的数据
     * @return 转换信息
     */
    private TransformationInfo extractTransformationInfo(ProcessedData data) {
        return new TransformationInfo(
            "groovy:default",
            "default",
            data.getDataSize(),
            System.currentTimeMillis()
        );
    }

    /**
     * 从数据中提取目标信息
     * 
     * @param data 处理后的数据
     * @return 目标信息
     */
    private TargetInfo extractTargetInfo(ProcessedData data) {
        // 从转换后的数据中提取目标表名
        String targetTable = "default_table";
        if (data.getTransformedData() != null && data.getTransformedData().containsKey("tableName")) {
            targetTable = data.getTransformedData().get("tableName").toString();
        }
        
        return new TargetInfo(
            "hive:" + targetTable,
            targetTable,
            "default",
            System.currentTimeMillis()
        );
    }

    /**
     * 查找上游数据ID
     * 
     * @param lineage 血缘关系
     * @return 上游数据ID
     */
    private String findUpstreamDataId(DataLineage lineage) {
        // 这里可以实现更复杂的上游数据查找逻辑
        // 简化实现：返回null
        return null;
    }

    /**
     * 查找下游数据ID列表
     * 
     * @param lineage 血缘关系
     * @return 下游数据ID列表
     */
    private List<String> findDownstreamDataIds(DataLineage lineage) {
        // 这里可以实现更复杂的下游数据查找逻辑
        // 简化实现：返回空列表
        return new ArrayList<>();
    }

    /**
     * 获取数据血缘统计信息
     * 
     * @return 统计信息
     */
    public DataLineageStatistics getStatistics() {
        return new DataLineageStatistics(
            totalLineageRecords.get(),
            totalLineageQueries.get(),
            totalLineageUpdates.get(),
            lineageMap.size(),
            lineageTrackingEnabled,
            maxLineageDepth,
            lineageRetentionDays,
            System.currentTimeMillis()
        );
    }

    /**
     * 设置血缘追踪配置
     * 
     * @param enabled 是否启用
     * @param maxDepth 最大深度
     * @param retentionDays 保留天数
     */
    public void setLineageTrackingConfig(boolean enabled, int maxDepth, long retentionDays) {
        this.lineageTrackingEnabled = enabled;
        this.maxLineageDepth = maxDepth;
        this.lineageRetentionDays = retentionDays;
        
        logger.info("数据血缘追踪配置已更新: 启用={}, 最大深度={}, 保留天数={}", enabled, maxDepth, retentionDays);
    }

    /**
     * 源信息类
     */
    public static class SourceInfo {
        private final String sourceId;
        private final String sourceName;
        private final int partition;
        private final long offset;
        private final long timestamp;

        public SourceInfo(String sourceId, String sourceName, int partition, long offset, long timestamp) {
            this.sourceId = sourceId;
            this.sourceName = sourceName;
            this.partition = partition;
            this.offset = offset;
            this.timestamp = timestamp;
        }

        // Getter方法
        public String getSourceId() { return sourceId; }
        public String getSourceName() { return sourceName; }
        public int getPartition() { return partition; }
        public long getOffset() { return offset; }
        public long getTimestamp() { return timestamp; }
    }

    /**
     * 转换信息类
     */
    public static class TransformationInfo {
        private final String transformationId;
        private final String transformationName;
        private final long dataSize;
        private final long timestamp;

        public TransformationInfo(String transformationId, String transformationName, long dataSize, long timestamp) {
            this.transformationId = transformationId;
            this.transformationName = transformationName;
            this.dataSize = dataSize;
            this.timestamp = timestamp;
        }

        // Getter方法
        public String getTransformationId() { return transformationId; }
        public String getTransformationName() { return transformationName; }
        public long getDataSize() { return dataSize; }
        public long getTimestamp() { return timestamp; }
    }

    /**
     * 目标信息类
     */
    public static class TargetInfo {
        private final String targetId;
        private final String targetName;
        private final String targetType;
        private final long timestamp;

        public TargetInfo(String targetId, String targetName, String targetType, long timestamp) {
            this.targetId = targetId;
            this.targetName = targetName;
            this.targetType = targetType;
            this.timestamp = timestamp;
        }

        // Getter方法
        public String getTargetId() { return targetId; }
        public String getTargetName() { return targetName; }
        public String getTargetType() { return targetType; }
        public long getTimestamp() { return timestamp; }
    }

    /**
     * 数据血缘类
     */
    public static class DataLineage {
        private final String dataId;
        private final SourceInfo sourceInfo;
        private final TransformationInfo transformationInfo;
        private final TargetInfo targetInfo;
        private final long timestamp;

        public DataLineage(String dataId, SourceInfo sourceInfo, TransformationInfo transformationInfo, 
                         TargetInfo targetInfo, long timestamp) {
            this.dataId = dataId;
            this.sourceInfo = sourceInfo;
            this.transformationInfo = transformationInfo;
            this.targetInfo = targetInfo;
            this.timestamp = timestamp;
        }

        // Getter方法
        public String getDataId() { return dataId; }
        public SourceInfo getSourceInfo() { return sourceInfo; }
        public TransformationInfo getTransformationInfo() { return transformationInfo; }
        public TargetInfo getTargetInfo() { return targetInfo; }
        public long getTimestamp() { return timestamp; }
    }

    /**
     * 数据血缘统计信息类
     */
    public static class DataLineageStatistics {
        private final long totalRecords;
        private final long totalQueries;
        private final long totalUpdates;
        private final int currentRecords;
        private final boolean trackingEnabled;
        private final int maxDepth;
        private final long retentionDays;
        private final long timestamp;

        public DataLineageStatistics(long totalRecords, long totalQueries, long totalUpdates,
                                   int currentRecords, boolean trackingEnabled, int maxDepth,
                                   long retentionDays, long timestamp) {
            this.totalRecords = totalRecords;
            this.totalQueries = totalQueries;
            this.totalUpdates = totalUpdates;
            this.currentRecords = currentRecords;
            this.trackingEnabled = trackingEnabled;
            this.maxDepth = maxDepth;
            this.retentionDays = retentionDays;
            this.timestamp = timestamp;
        }

        // Getter方法
        public long getTotalRecords() { return totalRecords; }
        public long getTotalQueries() { return totalQueries; }
        public long getTotalUpdates() { return totalUpdates; }
        public int getCurrentRecords() { return currentRecords; }
        public boolean isTrackingEnabled() { return trackingEnabled; }
        public int getMaxDepth() { return maxDepth; }
        public long getRetentionDays() { return retentionDays; }
        public long getTimestamp() { return timestamp; }
    }
}
